package com.security.manage.search.service;

import com.security.manage.search.model.*;
import com.security.manage.search.repository.*;
import com.security.manage.search.util.FastDfsClient;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.yaml.snakeyaml.reader.UnicodeReader;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class AsynService {

    @Resource
    private LogRepository logRepository;

    @Resource
    private UsbKeyStaticsRepository usbKeyStaticsRepository;

    @Resource
    private RegistryInfoRepository registryInfoRepository;

    @Resource
    private SoftInstallInfoRepository softInstallInfoRepository;

    @Resource
    private SoftChangeRepository softChangeRepository;

    @Resource
    private RegistryWarnRepository registryWarnRepository;

    @Resource
    private FireWalInfoRepository fireWalInfoRepository;

    @Resource
    private BrowserBookmarkRepository browserBookmarkRepository;

    @Resource
    private BrowserDownloadRepository browserDownloadRepository;

    @Resource
    private BrowserRecordRepository browserRecordRepository;

    @Resource
    private IpRepoRepository ipRepoRepository;

    @Resource
    private WarnInfoRepository warnInfoRepository;

    @Resource
    private UserMicroService userMicroService;

    @Resource
    private FilterRulesRepository filterRulesRepository;

    @Resource
    private FastDfsClient fastDfsClient;

    @Resource
    private FileInfoRepository fileInfoRepository;

    @Resource
    private ComputerInfoRepository computerInfoRepository;

    private Map<String, String> ipToRegion;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final String SECRET_KEY = "01234567890123456789123456123456";
    private static final String SECRET_IV = "0000000000000000";

    private Cipher cipher;

    private List<String> logTypes;
    private List<String> panBrowserRules;
    private List<String> panProcessRules;
    private List<String> mailBrowserRules;
    private List<String> mailProcessRules;

    private DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
    private DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");


    @PostConstruct
    public void init() {

        String[] types = {"Application", "Security", "Setup", "System", "ForwardedEvents", "HardwareEvents", "Key Management Service", "Windows PowerShell"};
        logTypes = Arrays.asList(types);
        try {
            SecretKeySpec keySpec = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), "AES");
            cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(SECRET_IV.getBytes()));
        } catch (Exception e) {

        }
        List<IprangeInfo> all = ipRepoRepository.findAll();
        List<IprangeInfo> infos = all.stream().filter(iprangeInfo -> !iprangeInfo.getCountry().contains("IANA")).collect(Collectors.toList());
        ipToRegion = infos.stream().collect(Collectors.toMap(iprangeInfo -> iprangeInfo.getIpStartNum() + "," + iprangeInfo.getIpEndNum(), iprangeInfo -> iprangeInfo.getCountry() + iprangeInfo.getArea()));
        logger.info("ipToRegion size:"+ipToRegion.size());
        List<FilterRules> rules = filterRulesRepository.findAll();

        List<String> panRules = rules.stream().filter(filterRules -> filterRules.getFilterType() == 1).map(FilterRules::getFilterRule).collect(Collectors.toList());
        panProcessRules = panRules.stream().filter(s -> s.contains("exe")).collect(Collectors.toList());
        panBrowserRules = panRules.stream().filter(s -> !s.contains("exe")).collect(Collectors.toList());
        List<String> mailRules = rules.stream().filter(filterRules -> filterRules.getFilterType() == 2).map(FilterRules::getFilterRule).collect(Collectors.toList());
        mailProcessRules = mailRules.stream().filter(s -> s.contains("exe")).collect(Collectors.toList());
        mailBrowserRules = mailRules.stream().filter(s -> !s.contains("exe")).collect(Collectors.toList());
        all.clear();
        infos.clear();
        all=null;
        infos=null;
    }

    private void getStartTimeAndEndTime(String uKey, String assetNumber, Long userId, String dateTime) {
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {

        }

        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("batchNumber", dateTime));
        boolQueryBuilder.must(QueryBuilders.termQuery("userId", userId));

        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        nativeSearchQueryBuilder.withPageable(PageRequest.of(0, 1));
        nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("recordTime").order(SortOrder.DESC));
        Page<Log> maxLogs = logRepository.search(nativeSearchQueryBuilder.build());

        NativeSearchQueryBuilder nativeSearchQueryBuilder2 = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQueryBuilder2 = QueryBuilders.boolQuery();
        boolQueryBuilder2.must(QueryBuilders.termQuery("batchNumber", dateTime));
        boolQueryBuilder2.must(QueryBuilders.termQuery("userId", userId));

        nativeSearchQueryBuilder2.withQuery(boolQueryBuilder2);
        nativeSearchQueryBuilder2.withPageable(PageRequest.of(0, 1));
        nativeSearchQueryBuilder2.withSort(SortBuilders.fieldSort("recordTime").order(SortOrder.ASC));
        Page<Log> minLogs = logRepository.search(nativeSearchQueryBuilder2.build());
        UsbKeyStatics statics = new UsbKeyStatics();
        statics.setUsbKey(uKey);
        statics.setAssetNumber(assetNumber);
        if (maxLogs.hasNext()) {
            statics.setStartTime(minLogs.iterator().next().getRecordTime());
        }else {
            return;
        }
        statics.setEndTime(maxLogs.iterator().next().getRecordTime());

        usbKeyStaticsRepository.save(statics);

    }

    @Async
    public void asynsUploadFileToFastDfs(String fileName,File file,
                                         Long userId,Long deptId,LocalDateTime fileTime){


        String fileAbsolutePath="";

        try {
            String ext = fileName.substring(fileName.lastIndexOf(".") + 1);
            InputStream fileStream = new FileInputStream(file);
            byte[] file_buff = null;
            int len1 = fileStream.available();
            file_buff = new byte[len1];
            fileStream.read(file_buff);
            FileModel file1 = new FileModel(fileName, file_buff, ext);
            fileAbsolutePath = fastDfsClient.uploadFile(file1);  //upload to fastdfs
        } catch (Exception e) {
            logger.error("upload fastdfs file Exception!:{}",e.getMessage());
        }

        FileInfo info = new FileInfo(fileName,file.length(),fileAbsolutePath,LocalDateTime.now(),userId,deptId);
        info.setCollectTime(fileTime);
        fileInfoRepository.save(info);
    }


    @Async
    public void parseFile(File directory, Long userId, Long deptId, String uKey,
                          String dateTime, LocalDateTime fileTime,String dateChange) {

        Map<String,String> nameToMd5 = new HashMap<>();
        try {
            File md5File = new File(directory,"md5.txt");
            //InputStreamReader inputStreamReader = new InputStreamReader();
            BufferedReader bufferedReader = new BufferedReader(new UnicodeReader(new FileInputStream(md5File)));
            //BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String text =null;
            while ((text = bufferedReader.readLine()) != null) {
                if ("".equals(text.trim())){
                    continue;
                }
                String[] ss = text.split("\t");
                nameToMd5.put(ss[0],ss[1]);
            }
        }catch (Exception e){
            return;
        }
        logger.info(nameToMd5.toString());
        String assetNumber="";
        for (File extractFile : directory.listFiles()) {
            long size = extractFile.length();
            String name = extractFile.getName();
            logger.info("name:"+name);
            if (size == 0 || "md5.txt".equals(name)) {
                continue;
            }
            InputStream zin = null;
            try {
                String fileMd5 = DigestUtils.md5Hex(new FileInputStream(extractFile));
                String md5 = nameToMd5.get(name);
                if (!md5.equals(fileMd5)){
                    continue;
                }

                zin = new FileInputStream(extractFile);
                if (name.toLowerCase().contains("hostinfo")) {
                    assetNumber = parseSoftwareFile(zin, fileTime, userId, deptId,dateChange);
                    continue;
                }
                if (name.toLowerCase().startsWith("firewall")) {
                    parseFirewallFile(zin, fileTime, userId, deptId,dateChange);
                    continue;
                }

                if (name.toLowerCase().contains("browsers")) {
                    parseBrowserFile(zin, userId, deptId,dateChange);
                    continue;
                }

                parseFile(zin, dateTime, userId, deptId,dateChange);
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                if (zin!=null){
                    try {
                        zin.close();
                    } catch (IOException e) {

                    }
                }
                extractFile.deleteOnExit();
            }
        }
        getStartTimeAndEndTime(uKey, assetNumber, userId, dateTime);
        logger.info("complete");
        directory.deleteOnExit();

    }

    private void parseBrowserFile(InputStream zin, Long userId, Long deptId,String dataChange) {
        InputStreamReader inputStreamReader = new InputStreamReader(zin);
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String text = null;
        try {
            List<BrowserBookmark> bookmarks = new ArrayList<>();
            List<BrowserDownload> downloads = new ArrayList<>();
            List<BrowserRecord> records = new ArrayList<>();
            int idx = 0;
            while ((text = bufferedReader.readLine()) != null) {
                if (idx == 0) {
                    text = text.substring(1);
                    idx = 2;
                }

                byte[] decode = Base64.getDecoder().decode(text);
                byte[] bytes = cipher.doFinal(decode);
                text = new String(bytes, "GBK");

                String[] ss = text.trim().split("\t");

                if (ss[0].contains("visit")) {
                    BrowserRecord record = new BrowserRecord();
                    record.setBrowserType(getBrowserType(ss[0]));
                    record.setUrl(ss[1]);
                    if(isRuleScope(panBrowserRules,ss[1])){
                        record.setPanFlag(1);
                    }
                    if(isRuleScope(mailBrowserRules,ss[1])){
                        record.setMailFlag(1);
                    }
                    record.setTitle(ss[2]);
                    try {
                        record.setVisitCount(Integer.parseInt(ss[3]));
                        record.setTypedCount(Integer.parseInt(ss[4]));
                        String updateTime = processTime(ss[5]);
                        LocalDateTime dateTime = LocalDateTime.parse(updateTime, dtf2);
                        record.setDateTime(getFinalFileTime(dateTime,dataChange));
                    } catch (Exception e) {
                        logger.info("browser - visit :" + text);
                        continue;
                    }

                    record.setUserId(userId);
                    record.setDeptId(deptId);
                    records.add(record);

                    continue;
                }
                if (ss[0].contains("bookmarks")) {
                    BrowserBookmark bookmark = new BrowserBookmark();
                    bookmark.setBrowserType(getBrowserType(ss[0]));
                    bookmark.setTitle(ss[1]);
                    try {
                        bookmark.setAddTime(getFinalFileTime(LocalDateTime.parse(ss[2], dtf2),dataChange));
                        bookmark.setLastUpdateTime(getFinalFileTime(LocalDateTime.parse(ss[3], dtf2),dataChange));
                    } catch (Exception e) {
                        logger.info("browser - bookmarks:" + text);
                        continue;
                    }

                    bookmark.setUserId(userId);
                    bookmark.setDeptId(deptId);
                    bookmarks.add(bookmark);
                    continue;
                }
                if (ss[0].contains("download")) {
                    BrowserDownload download = new BrowserDownload();
                    download.setBrowserType(getBrowserType(ss[0]));
                    download.setUrl(ss[1]);
                    download.setSavePath(ss[2]);
                    try {
                        download.setStartTime(getFinalFileTime(LocalDateTime.parse(ss[3], dtf2),dataChange));
                        download.setReceivedBytes(Long.parseLong(ss[4]));
                        download.setTotalBytes(Long.parseLong(ss[5]));
                        download.setEndTime(getFinalFileTime(LocalDateTime.parse(ss[6], dtf2),dataChange));
                    } catch (Exception e) {
                        logger.info("browser - download " + text);
                        continue;
                    }

                    download.setUserId(userId);
                    download.setDeptId(deptId);
                    downloads.add(download);
                }
            }

            if (records.size() > 0) {
                browserRecordRepository.saveAll(records);
            }
            if (bookmarks.size() > 0) {
                browserBookmarkRepository.saveAll(bookmarks);
            }
            if (downloads.size() > 0) {
                browserDownloadRepository.saveAll(downloads);
            }
        } catch (Exception e) {
        }
    }

    private String processTime(String s) {
        String[] dateTimes = s.split(" ");
        String[] dates = dateTimes[0].split("-");
        String updateMonth = StringUtils.leftPad(dates[1],2,"0");
        String updateDay = StringUtils.leftPad(dates[2],2,"0");
        return dates[0]+"-"+updateMonth+"-"+updateDay+" "+dateTimes[1];
    }

    private Integer getBrowserType(String s) {
        if (s.contains("ie")) {
            return 1;
        }
        if (s.contains("chrome")) {
            return 2;
        }
        if (s.contains("firefox")) {
            return 3;
        }
        return 0;
    }

    private void parseFirewallFile(InputStream zin, LocalDateTime fileTime, Long userId, Long deptId,String dateChange) {
        InputStreamReader inputStreamReader = new InputStreamReader(zin);
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String text = null;
        try {
            Set<FireWallInfo> infos = new HashSet<>();
            Set<WarnInfo> warnInfos = new HashSet<>();
            int idx = 0;
            Set<String> destSet = new HashSet<>();
            while ((text = bufferedReader.readLine()) != null) {
                if (idx == 0) {
                    text = text.substring(1);
                    idx = 2;
                }

                try {
                    byte[] decode = Base64.getDecoder().decode(text);
                    byte[] bytes = cipher.doFinal(decode);
                    text = new String(bytes, "GBK");
                }catch (Exception e){
                    continue;
                }

                if ("".equals(text.trim()) || text.trim().startsWith("#")) {
                    continue;
                }

                String[] ss = text.trim().split(" ");
                if (ss.length != 17) {
                    continue;
                }

                if (!"TCP".equals(ss[3])) {
                    continue;
                }

                if (!matchIp(ss[5]) || destSet.contains(ss[5])) {
                    continue;
                }
                FireWallInfo wallInfo = new FireWallInfo();
                try {
                    LocalDateTime parse = LocalDateTime.parse(ss[0] + " " + ss[1], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    wallInfo.setDateTime(getFinalFileTime(parse,dateChange));
                }catch (Exception e){
                    logger.error("text:{}",e.getMessage());
                    continue;
                }
                wallInfo.setAction(ss[2]);
                wallInfo.setProtocal(ss[3]);
                wallInfo.setSrcIp(ss[4]);
                wallInfo.setDestIp(ss[5]);
                long ipNum = ipToLong(ss[5]);
                String region = getIpRegion(ipNum);
                wallInfo.setIpRegion(region);
                if (!region.contains("中国")) {
                    wallInfo.setIpType(1);
                    WarnInfo info = new WarnInfo();
                    info.setIpAddress(ss[5]);
                    info.setWarnType(1);
                    info.setIpRegion(region);
                    info.setCreateTime(fileTime);
                    info.setUserId(userId);
                    info.setDeptId(deptId);
                    warnInfos.add(info);
                } else {
                    wallInfo.setIpType(2);
                }

                if (!"-".equals(ss[6])) {
                    wallInfo.setSrcPort(Integer.parseInt(ss[6]));
                }
                if (!"-".equals(ss[7])) {
                    wallInfo.setDestPort(Integer.parseInt(ss[7]));
                }
                wallInfo.setPath(ss[16]);
                wallInfo.setUserId(userId);
                wallInfo.setDeptId(deptId);
                destSet.add(wallInfo.getDestIp());
                infos.add(wallInfo);
            }
            logger.info(" firewall size:" + infos.size());
            if (infos.size() > 0) {
                fireWalInfoRepository.saveAll(infos);
            }

            if (warnInfos.size() > 0) {
                warnInfoRepository.saveAll(warnInfos);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String getIpRegion(long ip) {
        for (String key : ipToRegion.keySet()){
            String[] nums = key.split(",");
            if (ip<=Long.parseLong(nums[1])&&ip>=Long.parseLong(nums[0])){
                return ipToRegion.get(key);
            }
        }
        return "";
    }


    public long ipToLong(String ip) {
        String[] ipArray = ip.split("\\.");
        List<Long> ipNums = new ArrayList<>();
        for (int i = 0; i < 4; ++i) {
            ipNums.add(Long.parseLong(ipArray[i].trim()));
        }
        return ipNums.get(0)*256*256*256+ipNums.get(1)*256*256+ipNums.get(2)*256+ipNums.get(3);
    }

    private boolean matchIp(String ip) {
        String pattern = "((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(ip);
        return m.matches();
    }

    private String parseSoftwareFile(InputStream inputStream, LocalDateTime fileTime,
                                     Long userId, Long deptId,String dataChange) throws IOException {
        String text = null;
        List<SoftInstallInfo> softs = new ArrayList<>();
        List<RegistryInfo> registrys = new ArrayList<>();
        String cpuNumber = "";
        String macAddress = "";
        ComputerInfo computerInfo = new ComputerInfo();

        try {
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            int idx = 0;
            while ((text = bufferedReader.readLine()) != null) {

                if (idx == 0) {
                    text = text.substring(1);
                    idx = 2;
                }

                byte[] decode = Base64.getDecoder().decode(text);
                byte[] bytes = cipher.doFinal(decode);
                text = new String(bytes, "GBK");
                if (text.startsWith("ComputerName")) {
                    computerInfo.setComputerName(text.split("\t")[1]);
                    continue;
                }
                if (text.startsWith("CurrentUser")) {
                    computerInfo.setUserName(text.split("\t")[1]);
                    continue;
                }
                if (text.startsWith("SystemVersion")) {
                    computerInfo.setSystemVersion(text.split("\t")[1]);
                    continue;
                }
                if (text.startsWith("CPU")) {
                    computerInfo.setCpu(text.split("\t")[1]);
                    String[] cpus = text.split(",");
                    cpuNumber = cpus[cpus.length - 1];
                    computerInfo.setCpuNumber(cpuNumber);
                    continue;
                }
                if (text.startsWith("HardDiskInfo")) {
                    computerInfo.setDisks(text.split("\t")[1]);
                    continue;
                }

                if (text.startsWith("NetworkAdapterInfo")) {
                    computerInfo.setNetcards(text);
                    String[] networkAdapters = text.split(",");
                    for (String info:networkAdapters){
                        if (StringUtils.isEmpty(info)){
                            continue;
                        }
                        String[] infos = info.split("-");
                        if(judgeMacAddress(infos)){
                            macAddress = info;
                            computerInfo.setMacAddress(macAddress);
                            break;
                        }
                    }
                    continue;
                }

                if (text.startsWith("Software")) {
                    String[] texts = text.split("\t");
                    String[] data = texts[1].split(",");
                    if (data.length != 7) {
                        continue;
                    }
                    SoftInstallInfo soft = new SoftInstallInfo();
                    soft.setSoftName(data[0]);
                    soft.setSoftVersion(data[1]);
                    try {
                        LocalDate localDate = LocalDate.parse(data[2], dtf);
                        soft.setInstallDate(getFinalDate(localDate,dataChange));
                    } catch (Exception e) {
                        LocalDate localDate = LocalDate.parse("1970-01-01", dtf);
                        soft.setInstallDate(getFinalDate(localDate,dataChange));
                        logger.error("text:{}",text);
                    }
                    soft.setInstallLocation(data[3]);
                    soft.setInstallSource(data[4]);
                    soft.setSoftPublisher(data[5]);
                    soft.setUninstallStr(data[6]);
                    soft.setUserId(userId);
                    soft.setDeptId(deptId);
                    soft.setCreateTime(fileTime);
                    softs.add(soft);
                    continue;
                }

                if (text.startsWith("Registry")) {
                    String[] texts = text.split("\t");
                    String[] data = texts[1].split(",");
                    if (data.length != 3) {
                        continue;
                    }
                    RegistryInfo registry = new RegistryInfo();
                    registry.setRegistryPath(data[0]);
                    registry.setRegistryKey(data[1]);
                    registry.setRegistryValue(data[2]);
                    registry.setUserId(userId);
                    registry.setDeptId(deptId);
                    registry.setCreateTime(fileTime);
                    registrys.add(registry);
                }
            }
        } catch (Exception e) {
            logger.error("text:{}",text);
        } finally {
            inputStream.close();
        }
        logger.info("cpuNumber:{},macAddress:{}",cpuNumber,macAddress);
        ComputerInfo existComputer = computerInfoRepository.findByCpuNumberAndMacAddress(cpuNumber,macAddress);
        if (existComputer==null){
            computerInfo.setCreateTime(LocalDateTime.now());
            computerInfoRepository.save(computerInfo);
        }else{
            existComputer.setComputerName(computerInfo.getComputerName());
            existComputer.setCpu(computerInfo.getCpu());
            existComputer.setUserName(computerInfo.getUserName());
            existComputer.setSystemVersion(computerInfo.getSystemVersion());
            existComputer.setDisks(computerInfo.getDisks());
            existComputer.setNetcards(computerInfo.getNetcards());
            computerInfoRepository.save(existComputer);
        }

        List<SoftInstallInfo> infos = softInstallInfoRepository.findByUserId(userId);
        if (infos.size() > 0) {
            List<String> exist = infos.stream().map(SoftInstallInfo::getSoftName).collect(Collectors.toList());
            List<String> news = softs.stream().map(SoftInstallInfo::getSoftName).collect(Collectors.toList());
            List<String> retain = new ArrayList<>(exist);
            retain.retainAll(news);

            exist.removeAll(retain);
            news.removeAll(retain);
            List<SoftChange> changes = new ArrayList<>();
            for (SoftInstallInfo installInfo : infos) {
                if (exist.contains(installInfo.getSoftName())) {
                    SoftChange change = new SoftChange();
                    change.setSoftName(installInfo.getSoftName());
                    change.setChangeType(2);
                    change.setFirstTime(installInfo.getCreateTime());
                    change.setSecondTime(fileTime);
                    change.setUserId(userId);
                    change.setDeptId(deptId);
                    changes.add(change);
                }
            }

            for (SoftInstallInfo installInfo : softs) {
                if (news.contains(installInfo.getSoftName())) {
                    SoftChange change = new SoftChange();
                    change.setSoftName(installInfo.getSoftName());
                    change.setChangeType(1);
                    change.setFirstTime(installInfo.getCreateTime());
                    change.setSecondTime(fileTime);
                    change.setUserId(userId);
                    change.setDeptId(deptId);
                    changes.add(change);
                }
            }

            if (changes.size() > 0) {
                softChangeRepository.saveAll(changes);
            }
        }

        if (softs.size() > 0) {
            if (infos.size() > 0) {
                softInstallInfoRepository.removeAllByUserId(userId);
            }
            //解析zin 入库
            softInstallInfoRepository.saveAll(softs);
        }


        List<RegistryInfo> registryInfos = registryInfoRepository.findByUserId(userId);

        if (registryInfos.size() > 0) {
            Map<String, String> registryMap = registryInfos.stream().collect(Collectors.toMap(RegistryInfo::getRegistryKey, RegistryInfo::getRegistryValue));
            List<RegistryWarn> warns = new ArrayList<>();
            Set<WarnInfo> warnInfos = new HashSet<>();
            LocalDateTime lastTime = registryInfos.get(0).getCreateTime();
            for (RegistryInfo info : registrys) {
                String newValue = info.getRegistryValue();
                String lastValue = registryMap.get(info.getRegistryKey());
                if (!newValue.equals(lastValue)) {
                    RegistryWarn warn = new RegistryWarn();
                    warn.setRegistryKey(info.getRegistryKey());
                    warn.setRegistryValue1(lastValue);
                    warn.setRegistryValue2(newValue);
                    warn.setDeptId(deptId);
                    warn.setUserId(userId);
                    warn.setFirstTime(lastTime);
                    warn.setSecondTime(fileTime);
                    warns.add(warn);

                    WarnInfo warnInfo = new WarnInfo();
                    warnInfo.setRegistryKey(info.getRegistryKey());
                    warnInfo.setRegistryValue(newValue);
                    warnInfo.setUserId(userId);
                    warnInfo.setDeptId(deptId);
                    warnInfo.setWarnType(2);
                    warnInfo.setCreateTime(fileTime);
                    warnInfos.add(warnInfo);
                }
            }

            if (warns.size() > 0) {
                registryWarnRepository.saveAll(warns);
            }

            if (warnInfos.size() > 0) {
                warnInfoRepository.saveAll(warnInfos);
            }
        }

        if (registrys.size() > 0) {
            if (registryInfos.size() > 0) {
                registryInfoRepository.removeAllByUserId(userId);
            }
            //解析zin 入库
            registryInfoRepository.saveAll(registrys);
        }
        return computerInfo.getComputerName();
    }

    private boolean judgeMacAddress(String[] infos) {
        if (infos.length!=6){
            return false;
        }
        for (String info:infos){
            if (info.length()!=2){
                return  false;
            }
        }
        return  true;
    }


    private void parseFile(InputStream inputStream, String fileTime,
                           Long userId, Long deptId,String dataChange) {
        String text = null;

        try {
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            List<Log> infos = new ArrayList<>();
            int idx = 0;
            while ((text = bufferedReader.readLine()) != null) {
                text = text.trim();
                if ("".equals(text)) {
                    continue;
                }

                if (idx == 0) {
                    text = text.substring(1);
                    idx = 2;
                }

                try {
                    byte[] decode = Base64.getDecoder().decode(text);
                    byte[] bytes = cipher.doFinal(decode);
                    text = new String(bytes, "GBK");
                } catch (Exception e) {
                    e.printStackTrace();
                    continue;
                }

                String[] texts = text.split("\t");
                if (texts.length != 12) {
                    continue;
                }
                Log log = new Log();
                log.setId(getId());

                if (logTypes.contains(texts[0].trim())) {
                    log.setLogName(texts[0].trim().replace(" ", "-"));
                } else {
                    log.setLogName("Microsoft-Window");
                }
                log.setSource(texts[1].trim());
                try {
                    String time = texts[2];
                    if (texts[2].endsWith("00Z")) {
                        time = texts[2].substring(0, texts[2].length() - 5);
                    }
                    LocalDateTime parse = LocalDateTime.parse(time, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS"));
                    log.setRecordTime(getFinalFileTime(parse,dataChange));
                    log.setEventId(Integer.parseInt(texts[3].trim()));
                } catch (Exception e) {
                    logger.error("text:{}",e.getMessage());
                    continue;
                }

                log.setTask(texts[4].trim());
                log.setLevel(texts[5].trim());
                log.setOpcode(texts[6].trim());
                log.setKeyWord(texts[7].trim());
                log.setUser(texts[8].trim());
                log.setUserName(texts[9].trim());
                log.setComputer(texts[10].trim());
                String desc = texts[11].trim();
                if (desc.contains(".exe")) {
                    log.setLogName(log.getLogName() + ",Process");
                }
                if (desc.contains("File") || log.getEventId() == 4660 || log.getEventId() == 4663) {
                    log.setLogName(log.getLogName() + ",File");
                }
                if (isRuleScope(panProcessRules,desc)) {
                    log.setLogName(log.getLogName() + ",Pan-Windows");
                }
                if (isRuleScope(mailProcessRules,desc)) {
                    log.setLogName(log.getLogName() + ",Mail-Windows");
                }
                log.setDescription(desc);
                log.setUserId(userId);
                log.setDeptId(deptId);
                log.setBatchNumber(fileTime);
                infos.add(log);
            }
            logger.info("size:"+infos.size());
            if (infos.size() > 0) {
                logRepository.saveAll(infos);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("text:{}", text);
        }

    }

    private boolean isRuleScope(List<String> rules,String desc) {
        for (String key:rules){
            if (desc.contains(key)){
                return true;
            }
        }
        return false;
    }

    private String getId() {
        UUID uuid = UUID.randomUUID();
        return uuid.toString().replace("-", "");
    }

    public LocalDateTime getFinalFileTime(LocalDateTime dateTime, String dateChange) {

        if (StringUtils.isEmpty(dateChange)){
            return dateTime;
        }

        if (dateChange.contains("-")){
            String[] dates = dateChange.replace("-","").split("_");
            LocalDateTime dateTime1 = dateTime.minusYears(Long.parseLong(dates[0]));
            LocalDateTime dateTime2= dateTime1.minusMonths(Long.parseLong(dates[1]));
            LocalDateTime dateTime3 = dateTime2.minusDays(Long.parseLong(dates[2]));
            LocalDateTime dateTime4 = dateTime3.minusHours(Long.parseLong(dates[3]));
            LocalDateTime dateTime5 = dateTime4.minusMinutes(Long.parseLong(dates[4]));
            return dateTime5.minusSeconds(Long.parseLong(dates[5]));
        }else{
            String[] dates = dateChange.split("_");
            LocalDateTime dateTime1 = dateTime.plusYears(Long.parseLong(dates[0]));
            LocalDateTime dateTime2= dateTime1.plusMonths(Long.parseLong(dates[1]));
            LocalDateTime dateTime3 = dateTime2.plusDays(Long.parseLong(dates[2]));
            LocalDateTime dateTime4 = dateTime3.plusDays(Long.parseLong(dates[3]));
            LocalDateTime dateTime5 = dateTime4.plusMinutes(Long.parseLong(dates[4]));
            return dateTime5.minusSeconds(Long.parseLong(dates[5]));
        }
    }

    public LocalDate getFinalDate(LocalDate dateTime, String dateChange) {

        if (StringUtils.isEmpty(dateChange)){
            return dateTime;
        }

        if (dateChange.contains("-")){
            String[] dates = dateChange.replace("-","").split("_");
            LocalDate dateTime1 = dateTime.minusYears(Long.parseLong(dates[0]));
            LocalDate dateTime2= dateTime1.minusMonths(Long.parseLong(dates[1]));
            return dateTime2.minusDays(Long.parseLong(dates[2]));
        }else{
            String[] dates = dateChange.split("_");
            LocalDate dateTime1 = dateTime.plusYears(Long.parseLong(dates[0]));
            LocalDate dateTime2= dateTime1.plusMonths(Long.parseLong(dates[1]));
            return dateTime2.plusDays(Long.parseLong(dates[2]));
        }
    }


}
